# zennotac-backend/app/utils/remote_ssh.py
import paramiko
from scp import SCPClient
import os, json
from pathlib import Path
from app.config.base_setting import (
    backend_logger,
    REMOTE_HOSTS,
    PRIVATE_KEY_PATH,
    PRIVATE_KEY_PASS,
    REMOTE_INPUT_DIR,
    REMOTE_OUTPUT_DIR,
    OCR_OUTPUT_FOLDER,
)

def ssh_connect():
    backend_logger.info("🔐 Attempting SSH connections to fallback hosts...")

    for host_conf in REMOTE_HOSTS:
        host = host_conf["host"]
        port = host_conf.get("port", 22)
        username = host_conf["username"]

        backend_logger.info(f"🌐 Trying host {host}:{port}...")
        client = paramiko.SSHClient()
        client.set_missing_host_key_policy(paramiko.AutoAddPolicy())

        try:
            key = paramiko.RSAKey.from_private_key_file(PRIVATE_KEY_PATH, password=PRIVATE_KEY_PASS)
            client.connect(hostname=host, port=port, username=username, pkey=key)
            backend_logger.info(f"✅ SSH connected to {host}.")
            return client
        except Exception as e:
            backend_logger.warning(f"⚠️ Failed to connect to {host}: {e}")
            continue

    backend_logger.error("❌ All SSH connection attempts failed.")
    return None

def read_remote_progress_file(client, task_id: str) -> dict:
    """
    Read the progress file from the remote server via SSH.
    Returns parsed JSON data or None if not found or invalid.
    """

    remote_progress_path = f"/root/PaddleOCR/progress_{task_id}.json"
    backend_logger.info(f"📄 Attempting to read remote progress: {remote_progress_path}")

    try:
        stdin, stdout, stderr = client.exec_command(f"cat {remote_progress_path}")
        content = stdout.read().decode().strip()
        error = stderr.read().decode().strip()

        if error:
            backend_logger.warning(f"[SSH] stderr while reading file: {error}")
            return None

        if not content:
            backend_logger.warning(f"[SSH] File exists but is empty: {remote_progress_path}")
            return None

        progress_data = json.loads(content)
        backend_logger.debug(f"[SSH] Parsed progress data: {progress_data}")
        return progress_data

    except json.JSONDecodeError:
        backend_logger.error(f"[SSH] Invalid JSON in progress file: {remote_progress_path}")
        return None

    except Exception as e:
        backend_logger.error(f"[SSH] Exception while reading progress: {e}", exc_info=True)
        return None


def upload_file(client, local_path):
    backend_logger.info(f"📤 Uploading {local_path}...")
    with SCPClient(client.get_transport()) as scp:
        scp.put(local_path, REMOTE_INPUT_DIR)



def run_remote_script(client, filename, task_id):
    possible_interpreters = [
        "/root/miniconda3/envs/ocr/bin/python3",
        "/root/miniconda3/bin/python3",
        "/root/PaddleOCR/bin/python3",
        "python3"  # last resort: system PATH
    ]
    script_path = "/root/PaddleOCR/p2p_15_v5.py"
    # command_template = "{} {} --files '{}'"
    command_template = "{} {} --files '{}' --task_id '{}'"
    
    common_failure_keywords = [
        "No such file or directory",
        "command not found",
        "Permission denied",
        "ModuleNotFoundError",
        "No module named",
        "ImportError",
        "Traceback (most recent call last):"
    ]
    
    for interpreter in possible_interpreters:
        command = command_template.format(interpreter, script_path, filename, task_id)
        backend_logger.info(f"🚀 Trying OCR script: {command}")
        stdin, stdout, stderr = client.exec_command(command)

        stdout_output = stdout.read().decode().strip()
        stderr_output = stderr.read().decode().strip()

        # Log everything
        if stdout_output:
            backend_logger.info("[Remote] STDOUT:\n" + stdout_output)
        if stderr_output:
            backend_logger.warning("[Remote] STDERR:\n" + stderr_output)

        # If no known error, consider success
        if not any(err in stderr_output for err in common_failure_keywords):
            backend_logger.info(f"✅ Interpreter {interpreter} succeeded.")
            return

        backend_logger.warning(f"⚠️ Interpreter {interpreter} failed, trying next...")

    # All failed
    raise RuntimeError("❌ All interpreter attempts failed. OCR script could not be run.")


def download_file(client, original_filename: str, remote_filename: str):
    """
    Downloads the remote OCR output file to the local OCR_OUTPUT_FOLDER.
    Args:
        client: An active Paramiko SSHClient.
        original_filename: The original file name (before OCR).
        remote_filename: The corresponding OCR output file (e.g., 'doc1_ocred.pdf').
    """
    base = Path(remote_filename).stem  # We're now using the remote filename
    if base.endswith("_ocred"):
        base = base.removesuffix("_ocred")

    remote_path = os.path.join(REMOTE_OUTPUT_DIR, f"{base}_ocred.pdf")
    local_path = os.path.join(OCR_OUTPUT_FOLDER, f"{base}_ocred.pdf")

    backend_logger.info(f"📥 Downloading from {remote_path} to {local_path}")
    
    with SCPClient(client.get_transport()) as scp:
        # Optional: List remote output directory contents for debug
        stdin, stdout, stderr = client.exec_command(f"ls -lh {REMOTE_OUTPUT_DIR}")
        backend_logger.info(f"[Remote] Output folder: {OCR_OUTPUT_FOLDER} contents:\n" + stdout.read().decode())
        
        # Actual download
        scp.get(remote_path, local_path)


# def check_remote_file_exists(client, remote_path: str) -> bool:
#     try:
#         stdin, stdout, stderr = client.exec_command(f"test -f {remote_path} && echo exists || echo missing")
#         result = stdout.read().decode().strip()
#         return result == "exists"
#     except Exception as e:
#         backend_logger.error(f"[SSH] Error checking remote file: {str(e)}")
#         return False

# def execute_remote_command(client, command: str) -> str:
#     """
#     Execute a command on the remote server via an active SSH client.
#     Returns the stdout output.
#     """
#     try:
#         backend_logger.info(f"[SSH] Executing remote command: {command}")
#         stdin, stdout, stderr = client.exec_command(command)

#         # Read outputs
#         stdout_output = stdout.read().decode().strip()
#         stderr_output = stderr.read().decode().strip()

#         if stderr_output:
#             backend_logger.error(f"[SSH] Remote error output: {stderr_output}")

#         return stdout_output

#     except Exception as e:
#         backend_logger.error(f"[SSH] Error executing remote command: {str(e)}")
#         raise e